// Decompiled on 周六 2月 22 19:31:49 CST 2025 with Zomboid Decompiler v0.1.3 using Vineflower.
package zombie.vehicles;

import java.nio.ByteBuffer;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.List;
import java.util.TreeSet;
import org.joml.Quaternionf;
import zombie.core.physics.WorldSimulation;

public class VehicleInterpolation {
    int delay;
    int history;
    boolean buffering;
    private static final ArrayDeque<VehicleInterpolationData> pool = new ArrayDeque();
    private static final List<VehicleInterpolationData> outdated = new ArrayList();
    TreeSet<VehicleInterpolationData> buffer = new TreeSet();
    private static final Quaternionf tempQuaternionA = new Quaternionf();
    private static final Quaternionf tempQuaternionB = new Quaternionf();
    private static final VehicleInterpolationData temp = new VehicleInterpolationData();

    VehicleInterpolation() {
        this.reset();
        this.delay = 500;
        this.history = 800;
    }

    public void reset() {
        this.buffering = true;
        this.clear();
    }

    public void clear() {
        if (!this.buffer.isEmpty()) {
            pool.addAll(this.buffer);
            this.buffer.clear();
            outdated.clear();
        }
    }

    public void update(long time) {
        temp.time = time - (long)this.delay;
        VehicleInterpolationData vehicleInterpolationData0 = (VehicleInterpolationData)this.buffer.floor(temp);

        for (VehicleInterpolationData vehicleInterpolationData1 : this.buffer) {
            if (time - vehicleInterpolationData1.time > (long)this.history && vehicleInterpolationData1 != vehicleInterpolationData0) {
                outdated.add(vehicleInterpolationData1);
            }
        }

        outdated.forEach(this.buffer::remove);
        pool.addAll(outdated);
        outdated.clear();
        if (this.buffer.isEmpty()) {
            this.buffering = true;
        }
    }

    private void interpolationDataCurrentAdd(BaseVehicle baseVehicle) {
        VehicleInterpolationData vehicleInterpolationData = pool.isEmpty() ? new VehicleInterpolationData() : (VehicleInterpolationData)pool.pop();
        vehicleInterpolationData.time = zombie.GameTime.getServerTimeMills() - (long)this.delay;
        vehicleInterpolationData.x = baseVehicle.jniTransform.origin.x + WorldSimulation.instance.offsetX;
        vehicleInterpolationData.y = baseVehicle.jniTransform.origin.z + WorldSimulation.instance.offsetY;
        vehicleInterpolationData.z = baseVehicle.jniTransform.origin.y;
        Quaternionf quaternionf = baseVehicle.jniTransform.getRotation(new Quaternionf());
        vehicleInterpolationData.qx = quaternionf.x;
        vehicleInterpolationData.qy = quaternionf.y;
        vehicleInterpolationData.qz = quaternionf.z;
        vehicleInterpolationData.qw = quaternionf.w;
        vehicleInterpolationData.vx = baseVehicle.jniLinearVelocity.x;
        vehicleInterpolationData.vy = baseVehicle.jniLinearVelocity.y;
        vehicleInterpolationData.vz = baseVehicle.jniLinearVelocity.z;
        vehicleInterpolationData.engineSpeed = (float)baseVehicle.engineSpeed;
        vehicleInterpolationData.throttle = baseVehicle.throttle;
        vehicleInterpolationData.setNumWheels((short)baseVehicle.wheelInfo.length);

        for (int _int = 0; _int < vehicleInterpolationData.wheelsCount; _int++) {
            vehicleInterpolationData.wheelSteering[_int] = baseVehicle.wheelInfo[_int].steering;
            vehicleInterpolationData.wheelRotation[_int] = baseVehicle.wheelInfo[_int].rotation;
            vehicleInterpolationData.wheelSkidInfo[_int] = baseVehicle.wheelInfo[_int].skidInfo;
            vehicleInterpolationData.wheelSuspensionLength[_int] = baseVehicle.wheelInfo[_int].suspensionLength;
        }

        this.buffer.add(vehicleInterpolationData);
    }

    public void interpolationDataAdd(BaseVehicle vehicle, VehicleInterpolationData data) {
        VehicleInterpolationData vehicleInterpolationData = pool.isEmpty() ? new VehicleInterpolationData() : (VehicleInterpolationData)pool.pop();
        vehicleInterpolationData.copy(data);
        if (this.buffer.isEmpty()) {
            this.interpolationDataCurrentAdd(vehicle);
        }

        this.buffer.add(vehicleInterpolationData);
        this.update(zombie.GameTime.getServerTimeMills());
    }

    public void interpolationDataAdd(ByteBuffer bb, long time, float x, float y, float z, long currentTime) {
        VehicleInterpolationData vehicleInterpolationData = pool.isEmpty() ? new VehicleInterpolationData() : (VehicleInterpolationData)pool.pop();
        vehicleInterpolationData.time = time;
        vehicleInterpolationData.x = x;
        vehicleInterpolationData.y = y;
        vehicleInterpolationData.z = z;
        vehicleInterpolationData.qx = bb.getFloat();
        vehicleInterpolationData.qy = bb.getFloat();
        vehicleInterpolationData.qz = bb.getFloat();
        vehicleInterpolationData.qw = bb.getFloat();
        vehicleInterpolationData.vx = bb.getFloat();
        vehicleInterpolationData.vy = bb.getFloat();
        vehicleInterpolationData.vz = bb.getFloat();
        vehicleInterpolationData.engineSpeed = bb.getFloat();
        vehicleInterpolationData.throttle = bb.getFloat();
        vehicleInterpolationData.setNumWheels(bb.getShort());

        for (int _int = 0; _int < vehicleInterpolationData.wheelsCount; _int++) {
            vehicleInterpolationData.wheelSteering[_int] = bb.getFloat();
            vehicleInterpolationData.wheelRotation[_int] = bb.getFloat();
            vehicleInterpolationData.wheelSkidInfo[_int] = bb.getFloat();
            vehicleInterpolationData.wheelSuspensionLength[_int] = bb.getFloat();
        }

        this.buffer.add(vehicleInterpolationData);
        this.update(currentTime);
    }

    public boolean interpolationDataGet(float[] float0, float[] float1) {
        long _long = WorldSimulation.instance.time - (long)this.delay;
        return this.interpolationDataGet(float0, float1, _long);
    }

    public boolean interpolationDataGet(float[] float1, float[] float0, long _long) {
        temp.time = _long;
        VehicleInterpolationData vehicleInterpolationData0 = (VehicleInterpolationData)this.buffer.higher(temp);
        VehicleInterpolationData vehicleInterpolationData1 = (VehicleInterpolationData)this.buffer.floor(temp);
        if (this.buffering) {
            if (this.buffer.size() < 2 || vehicleInterpolationData0 == null || vehicleInterpolationData1 == null) {
                return false;
            }

            this.buffering = false;
        } else if (this.buffer.isEmpty()) {
            this.reset();
            return false;
        }

        int int0 = 0;
        if (vehicleInterpolationData0 == null) {
            if (vehicleInterpolationData1 == null) {
                this.reset();
                return false;
            } else {
                float0[0] = vehicleInterpolationData1.engineSpeed;
                float0[1] = vehicleInterpolationData1.throttle;
                float1[int0++] = vehicleInterpolationData1.x;
                float1[int0++] = vehicleInterpolationData1.y;
                float1[int0++] = vehicleInterpolationData1.z;
                float1[int0++] = vehicleInterpolationData1.qx;
                float1[int0++] = vehicleInterpolationData1.qy;
                float1[int0++] = vehicleInterpolationData1.qz;
                float1[int0++] = vehicleInterpolationData1.qw;
                float1[int0++] = vehicleInterpolationData1.vx;
                float1[int0++] = vehicleInterpolationData1.vy;
                float1[int0++] = vehicleInterpolationData1.vz;
                float1[int0++] = (float)vehicleInterpolationData1.wheelsCount;

                for (int int1 = 0; int1 < vehicleInterpolationData1.wheelsCount; int1++) {
                    float1[int0++] = vehicleInterpolationData1.wheelSteering[int1];
                    float1[int0++] = vehicleInterpolationData1.wheelRotation[int1];
                    float1[int0++] = vehicleInterpolationData1.wheelSkidInfo[int1];
                    float1[int0++] = vehicleInterpolationData1.wheelSuspensionLength[int1];
                }

                this.reset();
                return true;
            }
        } else if (vehicleInterpolationData1 != null && Math.abs(vehicleInterpolationData0.time - vehicleInterpolationData1.time) >= 10L) {
            float float2 = (float)(_long - vehicleInterpolationData1.time) / (float)(vehicleInterpolationData0.time - vehicleInterpolationData1.time);
            float0[0] = (vehicleInterpolationData0.engineSpeed - vehicleInterpolationData1.engineSpeed) * float2 + vehicleInterpolationData1.engineSpeed;
            float0[1] = (vehicleInterpolationData0.throttle - vehicleInterpolationData1.throttle) * float2 + vehicleInterpolationData1.throttle;
            float1[int0++] = (vehicleInterpolationData0.x - vehicleInterpolationData1.x) * float2 + vehicleInterpolationData1.x;
            float1[int0++] = (vehicleInterpolationData0.y - vehicleInterpolationData1.y) * float2 + vehicleInterpolationData1.y;
            float1[int0++] = (vehicleInterpolationData0.z - vehicleInterpolationData1.z) * float2 + vehicleInterpolationData1.z;
            tempQuaternionA.set(vehicleInterpolationData1.qx, vehicleInterpolationData1.qy, vehicleInterpolationData1.qz, vehicleInterpolationData1.qw);
            tempQuaternionB.set(vehicleInterpolationData0.qx, vehicleInterpolationData0.qy, vehicleInterpolationData0.qz, vehicleInterpolationData0.qw);
            tempQuaternionA.nlerp(tempQuaternionB, float2);
            float1[int0++] = tempQuaternionA.x;
            float1[int0++] = tempQuaternionA.y;
            float1[int0++] = tempQuaternionA.z;
            float1[int0++] = tempQuaternionA.w;
            float1[int0++] = (vehicleInterpolationData0.vx - vehicleInterpolationData1.vx) * float2 + vehicleInterpolationData1.vx;
            float1[int0++] = (vehicleInterpolationData0.vy - vehicleInterpolationData1.vy) * float2 + vehicleInterpolationData1.vy;
            float1[int0++] = (vehicleInterpolationData0.vz - vehicleInterpolationData1.vz) * float2 + vehicleInterpolationData1.vz;
            float1[int0++] = (float)vehicleInterpolationData0.wheelsCount;

            for (int int2 = 0; int2 < vehicleInterpolationData0.wheelsCount; int2++) {
                float1[int0++] = (vehicleInterpolationData0.wheelSteering[int2] - vehicleInterpolationData1.wheelSteering[int2]) * float2
                    + vehicleInterpolationData1.wheelSteering[int2];
                float1[int0++] = (vehicleInterpolationData0.wheelRotation[int2] - vehicleInterpolationData1.wheelRotation[int2]) * float2
                    + vehicleInterpolationData1.wheelRotation[int2];
                float1[int0++] = (vehicleInterpolationData0.wheelSkidInfo[int2] - vehicleInterpolationData1.wheelSkidInfo[int2]) * float2
                    + vehicleInterpolationData1.wheelSkidInfo[int2];
                float1[int0++] = (vehicleInterpolationData0.wheelSuspensionLength[int2] - vehicleInterpolationData1.wheelSuspensionLength[int2]) * float2
                    + vehicleInterpolationData1.wheelSuspensionLength[int2];
            }

            return true;
        } else {
            return false;
        }
    }
}
